
include('graphics.node');
include('events');

var raf = ( function() {
    return window.webkitRequestAnimationFrame ||
           window.mozRequestAnimationFrame ||
           window.oRequestAnimationFrame ||
           window.msRequestAnimationFrame ||
           function( callback, element ) {
             window.setTimeout( callback, 1000 / 60 );
           };
  } )();

new_class(
  'graphics.Director',
  function(canvas) {
    this._canvas = canvas;
    this._context = canvas.getContext("2d");
    this._layers = {};
    this._root = new graphics.Node();
    this._lastStep = new Date;
  },
  {
    start: function() {
      this._stop = false;
      this.step();
    },
    stop: function() {
      this._stop = true;
    },
    addLayer: function(name, index) {
      if (name === undefined) {
        throw "Must specify a name.";
      }
      var l = new graphics.Node();
      l.z = index || 0;
      this._root.addChild(l);
      this._layers[name] = l;
    },
    layer: function(name) {
      if (!(name in this._layers)) {
        throw "Invalid layer name: " + name;
      }
      return this._layers[name];
    },
    step: function() {
      if (this._stop) return;
      var dt = ((new Date) - this._lastStep) / 1000;
      this._lastStep = new Date;
      raf(bind(this.step, this));
      this.notify('willStep', dt);
      this.clear();
      this.update(dt);
      this.notify('didStep');
    },
    clear: function() {
      this._canvas.width = this._canvas.width;  // hard reset
    },
    update: function(dt) {
      this._root._step(this, dt);
    },

    // Graphic functions.
    getContext: function() {
      return this._context;
    },
    translate: function(x, y) {
      this._context.translate(x, y);
    },
    scale: function(x, y) {
      this._context.scale(x, y);
    },
    rotate: function(a) {
      this._context.rotate(a);
    },
    save: function() {
      this._context.save();
    },
    restore: function() {
      this._context.restore();
    },
    drawImage: function(a,b,c) {
      this._context.drawImage(a,b,c);
    },
    // Clears the viewport and writes centered text.
    writeToScreen: function(text) {
      // TODO(stevet): Take more parameters.
      var context = this._context
      this.clear();
      context.fillStyle    = '#f00';
      context.font         = 'bold italic 90px sans-serif';
      context.textAlign    = 'center';
      context.textBaseline = 'middle';
      context.fillText  (text, this._canvas.width/2, this._canvas.height/2);
    },
  });

add_events_to_class(graphics.Director);
